/*
 * Created on April 27, 2005
 *
 * Copyright (c) Patrick Armstrong 2002-2007. All Rights Reserved
 */
package org.dime.mine.bot;

import java.util.Collection;

import org.dime.mine.bot.AwareBoard.AwareLocation;
import org.dime.mine.game.Board;

/**
 * Truth is a solution algorithm. It visits each position in the board, if a
 * position requires the same number of mines as it has unknowns then it marks
 * each unknown as a mine. If a position has satisfied its number of mines then
 * truth will open any remaining unknowns.
 * 
 * @author Owner
 */
public class Truth extends AbstractStrategy
{
    @Override
    public boolean execute(Board board)
    {
        AwareBoard awareBoard = new AwareBoard(board);
        for (AwareLocation location : awareBoard.getUnsolvedLocations())
        {
            if (executeHelper(awareBoard, location))
                return true;
        }
        return false;
    }

    private boolean executeHelper(AwareBoard board, AwareBoard.AwareLocation loc)
    {
        boolean flag = false;
        if (loc.isSatisfied())
        {
            open(board, loc);
            flag = true;
        }
        else if (loc.getValue() == loc.getMarks() + loc.getUnknowns())
        {
            mark(board, loc);
            flag = true;
        }
        return flag;
    }

    private void open(AwareBoard board, AwareBoard.AwareLocation loc)
    {
        Collection<AwareLocation> neighbors = board.getNeighborhood(loc
                .getRow(), loc.getColumn());
        for (AwareLocation neighbor : neighbors)
        {
            board.open(neighbor.getRow(), neighbor.getColumn());
        }
    }

    private void mark(AwareBoard board, AwareBoard.AwareLocation loc)
    {
        Collection<AwareLocation> neighbors = board.getNeighborhood(loc
                .getRow(), loc.getColumn());
        for (AwareLocation neighbor : neighbors)
        {
            if (!neighbor.isMarked())
                board.setMarked(neighbor.getRow(), neighbor.getColumn(), true);
        }
    }
}